package org.piggy.core.utils;

import com.fasterxml.jackson.databind.node.ObjectNode;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.handler.codec.http.*;
import org.asynchttpclient.Response;
import org.piggy.common.constants.BasicConst;
import org.piggy.common.enums.ResponseCode;
import org.piggy.common.utils.JsonUtil;
import org.piggy.core.context.Context;
import org.piggy.core.reponse.GatewayResponse;
import java.nio.ByteBuffer;

public class ResponseUtil {


	public static FullHttpResponse getHttpResponse(ResponseCode responseCode) {
		GatewayResponse gatewayResponse = ResponseUtil.buildGatewayResponse(responseCode);
		DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.INTERNAL_SERVER_ERROR,
				Unpooled.wrappedBuffer(gatewayResponse.getContent().getBytes()));
		
		httpResponse.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON + ";charset=utf-8");
		httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().readableBytes());
		return httpResponse;
	}
	

	private static FullHttpResponse getHttpResponse(GatewayResponse gatewayResponse) {
		ByteBuf content;
		if(gatewayResponse.getResponse() != null) {
			ByteBuffer buffer = gatewayResponse.getResponse().getResponseBodyAsByteBuffer();
			content = Unpooled.wrappedBuffer(buffer);
		}
		else if (gatewayResponse.getContent() != null) {
			content = Unpooled.wrappedBuffer(gatewayResponse.getContent().getBytes());
		}
		else {
			content = Unpooled.wrappedBuffer(BasicConst.BLANK_SEPARATOR_1.getBytes());
		}
		
		if(gatewayResponse.getResponse() == null) {
			HttpResponseStatus httpResponseStatus = gatewayResponse.getHttpResponseStatus();
			DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, content);
			httpResponse.headers().add(gatewayResponse.getResponseHeaders());
			httpResponse.headers().add(gatewayResponse.getExtraResponseHeaders());
			httpResponse.headers().set(HttpHeaderNames.CONTENT_LENGTH, httpResponse.content().readableBytes());
			return httpResponse;
		}
		else {
			int statusCode = gatewayResponse.getResponse().getStatusCode();
			HttpResponseStatus httpResponseStatus = HttpResponseStatus.valueOf(statusCode);
			DefaultFullHttpResponse httpResponse = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, httpResponseStatus, content);
			httpResponse.headers().add(gatewayResponse.getResponse().getHeaders());
			httpResponse.headers().add(gatewayResponse.getExtraResponseHeaders());
			return httpResponse;
		}
	}
	

	/**
	 * 写回响应信息方法
	 */
	public static void writeResponse(Context context) {
		if(context.isWritten()) {
			//	1 第一步构建响应对象
			FullHttpResponse httpResponse = ResponseUtil.getHttpResponse(context.getGatewayResponse());
			if(!context.isKeepAlive()) {
				context.getChannelHandlerContext().writeAndFlush(httpResponse).addListener(ChannelFutureListener.CLOSE);
			} else {
				httpResponse.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
				context.getChannelHandlerContext().writeAndFlush(httpResponse);
			}
			//	2 设置写回结束状态为 COMPLETED
			context.completed();
		}
	}


	// asynchttpclient result
	public static GatewayResponse buildGatewayResponse(Response response){
		GatewayResponse gatewayResponse = new GatewayResponse();
		gatewayResponse.setResponse(response);
		gatewayResponse.setHttpResponseStatus(HttpResponseStatus.valueOf(response.getStatusCode()));
		return gatewayResponse;
	}

	// other result
	public static GatewayResponse buildGatewayResponse(Object object){
		ObjectNode objectNode = JsonUtil.createObjectNode();
		if(object instanceof ResponseCode code){
			objectNode.put(JsonUtil.STATUS, code.getStatus().code());
			objectNode.put(JsonUtil.CODE, code.getCode());
		}
		objectNode.putPOJO(JsonUtil.DATA, object);
		GatewayResponse gatewayResponse = new GatewayResponse();
		gatewayResponse.setHttpResponseStatus(ResponseCode.SUCCESS.getStatus());
		gatewayResponse.putHeader(HttpHeaderNames.CONTENT_TYPE,HttpHeaderValues.APPLICATION_JSON+";charset=utf-8");
		gatewayResponse.setContent(JsonUtil.toJSONString(objectNode));
		return gatewayResponse;
	}
	
}
